home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / appl / napsaterm / amigadisplay.c < prev    next >
C/C++ Source or Header  |  1994-05-14  |  21KB  |  886 lines

  1. RCS_ID_C="$Id: amigadisplay.c,v 3.2 1994/01/08 08:51:57 ppessi Exp $";
  2. /*
  3.  * amigadisplay.c --- Rastport drawing routines for napsaterm
  4.  *
  5.  * Author: ppessi <Pekka.Pessi@hut.fi>
  6.  *
  7.  * Copyright © 1993 Pekka Pessi
  8.  *
  9.  * Last modified: Sat Jan  8 07:42:35 1994 ppessi
  10.  *
  11.  * Copyright 1989, Chris Newman.  Changes Copyright 1989, Todd Williamson.
  12.  * All Rights Reserved
  13.  * Permission is granted to copy, modify, and use this as long
  14.  * as this notice remains intact.  This is a nifty program.
  15.  *
  16.  * Parts of this program were swiped from Joe Keane's jterm, and other parts
  17.  * were swiped from ITC's h19 terminal.
  18.  *
  19.  * DISCLAIMER: the author (and maintainer) of this program is not responsible
  20.  * for any damage or other problems caused by it.
  21.  *
  22.  * $Author: ppessi $ $Revision: 3.2 $ $Date: 1994/01/08 08:51:57 $
  23.  */
  24.  
  25. #include <assert.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <ctype.h>
  29. #include "nifty.h"
  30. #include "amiga.h"
  31. #include "display.h"
  32. #include "dispmacros.h"
  33. #include "napsaprefs.h"
  34. #include "nio.h"
  35.  
  36. #include "wimp.h"
  37.  
  38. #include <graphics/gfxmacros.h>
  39. /* imported globals */
  40. extern int vt100_yucky_wrap_mode;   /* hack to do v100's wrap mode */
  41.  
  42. #define INVERT 0x50        /* Useful MinTerms  */
  43. #define WHITE  0x00
  44. #define BLACK  0xff
  45.  
  46. #define DEFDRMD JAM2        /* The default drawing mode */
  47.  
  48. /* Blitter call made to entire display.  Pass in the MinTerm */
  49. #define    INVERTALL(mode) \
  50.     BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(0), POSY(0),\
  51.               wm.x, wm.y, (mode))
  52.  
  53. static void wmputs(int x, int y, unsigned char *stng, int style);
  54.  
  55. struct RastPort *rp = NULL;     /* Drawing rastport */
  56. struct RastPort myrp;        /* A copy of Windows rastport */
  57.  
  58. /* current flash mode: 0 = not inverse */
  59. static int flashmode = 0;        
  60.  
  61. /* Output string with default style */
  62. static void putstring(short x, short y, const char *string, int len) 
  63.     if (disp.invert) 
  64.         SetDrMd(rp, DEFDRMD | INVERSVID); 
  65.  
  66.     Move(rp, STYLEFLAG(y) & DOUBLE_MASK ? POSX(x) << 1 : POSX(x), 
  67.         POSY(y) + wm.font.b); 
  68.  
  69.     if (np.national == NAT_7BIT) {
  70.     UBYTE shown[MAXWIDTH + 1];
  71.     long cnt = 0;
  72.     for (; cnt < len; )
  73.         shown[cnt++] = national_show[(UBYTE)*string++];
  74.     Text(rp, shown, len);
  75.     } else 
  76.     Text(rp, (UBYTE *)string, len);
  77.  
  78.     if (disp.invert)
  79.         SetDrMd(rp, DEFDRMD); 
  80. }
  81.  
  82. /* this macro outputs a string with styles */
  83. static void styleput(short x, short y, 
  84.              const char *string, short len, int style)
  85.     int    sputswflag = (STYLEFLAG(y) & DOUBLE_MASK) != 0; 
  86.  
  87.     putstring(x, y, string, len); 
  88.     if (XOR((style) & INVERSE,(style) &    FLASH && flashmode)) { 
  89.     BltBitMapRastPort(rp->BitMap, 0, 0, rp, 
  90.               POSX(x << sputswflag), POSY(y), 
  91.                       wm.font.w * len << sputswflag, 
  92.               wm.font.h, INVERT); 
  93.     }
  94. }
  95.  
  96. /* 
  97.  * Set appropriate font
  98.  */
  99. #define SETFONT(style, line) \
  100.   setfont(rp, ((style) | (STYLEFLAG(line) & DOUBLE_MASK)) & ATTRIB_MASK)
  101.  
  102. void dssetfont(register short style, register int line)
  103. {
  104.   /* Do only when mapped */
  105.   if (rp)
  106.     SETFONT(style, line);
  107. }
  108.  
  109.  
  110. static int cursormode = 0;    /* current cursor state 1=visible */
  111.  
  112. /*
  113.  * cursor display routine
  114.  */
  115. void dscursoron(void)
  116. {
  117.     if (rp) {
  118.     int wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) != 0;
  119.     if (!cursormode) {
  120.         cursormode = 1;
  121.         if (disp.visual == CUR_BLOCK) {
  122.         BltBitMapRastPort(rp->BitMap, 1, 1, rp, 
  123.                   POSX(disp.curx << wflag),
  124.                   POSY(disp.cury), 
  125.                   wm.font.w << wflag, wm.font.h, INVERT);
  126.         }
  127.         else if (disp.visual == CUR_UNDERLINE) {
  128.         BltBitMapRastPort(rp->BitMap, 1, 1, rp, 
  129.                   POSX(disp.curx << wflag),
  130.                   POSY(disp.cury) + wm.font.b + 1, 
  131.                   wm.font.w << wflag, 1, INVERT);
  132.         }
  133.     }
  134.     }
  135. }
  136.  
  137. void dscursoroff(void)
  138. {
  139.     if (rp) {
  140.     int wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) != 0;
  141.  
  142.     if (isSelection()) 
  143.         killSelection();
  144.     if (cursormode) {
  145.         cursormode = 0;
  146.         if (disp.visual == CUR_BLOCK) {
  147.         BltBitMapRastPort(rp->BitMap, 1, 1, rp, 
  148.                   POSX(disp.curx << wflag),
  149.                   POSY(disp.cury), 
  150.                   wm.font.w << wflag, 
  151.                   wm.font.h, 
  152.                   INVERT);
  153.         } else if (disp.visual == CUR_UNDERLINE) {
  154.         BltBitMapRastPort(rp->BitMap, 1, 1, rp, 
  155.                   POSX(disp.curx << wflag),
  156.                   POSY(disp.cury) + wm.font.b + 1, 
  157.                   wm.font.w << wflag, 
  158.                   1, 
  159.                   INVERT);
  160.         }
  161.     }
  162.     }
  163. }
  164.  
  165. void dscursorblink(void)
  166. {
  167.     if (rp) {
  168.     int wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) != 0;
  169.  
  170.     cursormode = !cursormode;
  171.     if (disp.visual == CUR_BLOCK) {
  172.             BltBitMapRastPort(rp->BitMap, 1, 1, rp, 
  173.                   POSX(disp.curx << wflag),
  174.                       POSY(disp.cury), 
  175.                   wm.font.w << wflag, 
  176.                   wm.font.h, 
  177.                   INVERT);
  178.         }
  179.     else if (disp.visual == CUR_UNDERLINE) {
  180.             BltBitMapRastPort(rp->BitMap, 1, 1, rp,
  181.                   POSX(disp.curx << wflag),
  182.                       POSY(disp.cury) + wm.font.b + 1, 
  183.                   wm.font.w << wflag, 
  184.                   1, 
  185.                   INVERT);
  186.         }
  187.     }
  188. }
  189.  
  190. long dsflashinit(void)
  191. {
  192.     timereq->tr_time.tv_secs = 1;
  193.     timereq->tr_time.tv_micro = 0;
  194.     timereq->tr_node.io_Command = TR_ADDREQUEST;
  195.     SendIO((struct IORequest *)timereq);
  196.  
  197.     return 1 << timeport->mp_SigBit;
  198. }
  199.  
  200. void dscheckflash(void)
  201. {
  202.     register int x, y, xhome;
  203.     int linelen;
  204.  
  205.     if (CheckIO(timereq)) {
  206.     WaitIO(timereq);
  207.     dsflashinit();
  208.     }
  209.  
  210.     if (!rp) return;
  211.  
  212.     flashmode = !flashmode;
  213.  
  214.     /* flash cursor */
  215.     if (disp.blink) 
  216.     dscursorblink();
  217.  
  218.     /* flash flashing text  */
  219.     for (y = 0; y < disp.winheight; y++)
  220.     if (STYLEFLAG(y) & FLASH && (linelen = LINELEN(y))) {
  221.         int wflag = (STYLEFLAG(y) & DOUBLE_MASK) != 0;
  222.         for (xhome = -1, x = 0; x <= linelen; x++)
  223.         if (x < linelen && (STYLEPOS(x,y) & FLASH)) {
  224.             if (xhome < 0)
  225.             xhome = x;
  226.         } else if (xhome > -1) {
  227.             BltBitMapRastPort(rp->BitMap, 0, 0, rp, 
  228.                       POSX(xhome << wflag), POSY(y), 
  229.                       (x - xhome) * wm.font.w << wflag, 
  230.                       wm.font.h, INVERT);
  231.             xhome = -1;
  232.         } else
  233.             xhome = -1;
  234.     }
  235. }
  236.  
  237.  
  238. /*
  239.  * redraw one line -- used for double width
  240.  */
  241. void redraw_line(int y)
  242. {
  243.     register int    x;
  244.     register char   *temp;
  245.     int            homex, style, linelen;
  246.     char        *tempmin, tempc;
  247.     short        wflag = (STYLEFLAG(y) & DOUBLE_MASK) != 0;
  248.  
  249.     if (!rp)
  250.     return;
  251.  
  252.     SETFONT(0, y);
  253.     BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(0), POSY(y), 
  254.                       wm.font.w * disp.winwidth, wm.font.h, 
  255.               disp.invert ? BLACK : WHITE);
  256.  
  257.     if ((linelen = LINELEN(y)) >= (disp.winwidth >> wflag))
  258.     linelen = (disp.winwidth >> wflag) - 1;
  259.  
  260.     if (linelen && !STYLEFLAG(y)) {
  261.     temp = (tempmin = TEXTLINE(y)) + linelen;
  262.     tempc = *temp;
  263.     *temp = 0;
  264.     putstring(0, y, tempmin, strlen(tempmin));
  265.     *temp = tempc;
  266.     } else if (linelen && STYLEFLAG(y) > 0) {
  267.     temp = tempmin = TEXTLINE(y);
  268.     style = STYLEPOS(0, y);
  269.     for (homex = x = 0; x <= linelen; x++) {
  270.         if (x < linelen && STYLEPOS(x, y) == style) {
  271.         temp++;
  272.         continue;
  273.         }
  274.         tempc = *temp;
  275.         *temp = 0;
  276.         if (style & ATTRIB_MASK)
  277.         SETFONT(style, y);
  278.         styleput(homex, y, tempmin, x - homex, style);
  279.         *temp = tempc;
  280.         tempmin = temp++;
  281.         if (style & ATTRIB_MASK)
  282.         SETFONT(0, y);
  283.         if (x < linelen) {
  284.         homex = x;
  285.         style = STYLEPOS(x, y);
  286.         }
  287.     }
  288.     }
  289.     SETFONT(disp.style, disp.cury);
  290. }
  291.  
  292. /*
  293.  * redraw the display
  294.  */
  295. void redraw_display(int resize)
  296. {
  297.     register int    x, y;
  298.     register char   *temp;
  299.     int            homex, style, linelen, wflag;
  300.     char        *tempmin, tempc;
  301.  
  302.     if (((resize || !rp) && !resize_display()) || !rp)
  303.     return;
  304.  
  305.     SETFONT(0, 0);
  306.     if (disp.invert) {
  307.     INVERTALL(BLACK);
  308.     } else
  309.         INVERTALL(WHITE);
  310.     cursormode = 0;
  311.     for (y = 0; y < disp.winheight; y++) {
  312.     wflag = (STYLEFLAG(y) & DOUBLE_MASK) != 0;
  313.     dssetfont(STYLEFLAG(y), y);
  314.     if ((linelen = LINELEN(y)) >= (disp.winwidth >> wflag))
  315.         linelen = (disp.winwidth >> wflag) - 1;
  316.     if (linelen && !STYLEFLAG(y)) {
  317.         temp = (tempmin = TEXTLINE(y)) + linelen;
  318.         tempc = *temp;
  319.         *temp = 0;
  320.         putstring(0, y, tempmin, strlen(tempmin));
  321.         *temp = tempc;
  322.     } else if (linelen != 0 && STYLEFLAG(y) > 0) {
  323.         temp = tempmin = TEXTLINE(y);
  324.         style = STYLEPOS(0, y);
  325.         for (homex = x = 0; x <= linelen + 1; x++) {
  326.         if (x <= linelen && STYLEPOS(x, y) == style) {
  327.             temp++;
  328.             continue;
  329.         }
  330.         tempc = *temp;
  331.         *temp = 0;
  332.         if (style & ATTRIB_MASK)
  333.             SETFONT(style, y);
  334.         styleput(homex, y, tempmin, x - homex, style);
  335.         *temp = tempc;
  336.         tempmin = temp++;
  337.         if (style & ATTRIB_MASK)
  338.             dssetfont(0, y);
  339.         if (x < linelen) {
  340.             homex = x;
  341.             style = STYLEPOS(x, y);
  342.         }
  343.         }
  344.     }
  345.     }
  346.  
  347.     if (isSelection()) {
  348.     invertSelection();
  349.     } else {
  350.     dscursoron();
  351.     }
  352.     SETFONT(disp.style, disp.cury);
  353. }
  354.  
  355. /*
  356.  * Show centered text
  357.  */
  358. void showbanner(struct RastPort *rp, char *text)
  359. {
  360.   size_t l = strlen(text);
  361.  
  362.   SetWrMsk(rp, 1);
  363.  
  364.   if (disp.invert) {
  365.     INVERTALL(BLACK);
  366.   } else {
  367.     INVERTALL(WHITE);
  368.   }
  369.  
  370.   if (wm.x < l * wm.font.w || wm.y < wm.font.h)
  371.     return;
  372.  
  373.   cursormode = 0;
  374.  
  375.   Move(rp, (POSX(wm.x) - l * wm.font.w) / 2, (POSY(wm.y) - wm.font.h) / 2);
  376.  
  377.   if (disp.invert) 
  378.     SetDrMd(rp, DEFDRMD | INVERSVID);
  379.  
  380.   Text(rp, text, l);
  381.  
  382.   if (disp.invert) 
  383.     SetDrMd(rp, DEFDRMD);
  384. }
  385.  
  386.  
  387. /*
  388.  * scrolling routines
  389.  */
  390. void dsscroll(int y, int numlines, int amount)
  391. {
  392.     if (rp) {
  393.     if (ABS(amount) < numlines) {
  394.         if(disp.invert) 
  395.         SetBPen(rp, 1);    
  396.         ScrollRaster(rp, 0, amount*wm.font.h, POSX(0), POSY(y), 
  397.              POSX(disp.winwidth),
  398.              POSY(y)+numlines*wm.font.h-1);
  399.         if(disp.invert) 
  400.         SetBPen(rp, 0);    
  401.     } else if(ABS(amount) >= numlines) 
  402.         BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(0), POSY(y), 
  403.                   wm.font.w*disp.winwidth, numlines*wm.font.h, 
  404.                   disp.invert ? BLACK : WHITE);
  405.     }
  406.  
  407.     if (ABS(amount) < (numlines)) {
  408.         register char *templ;
  409.         register short *templs;
  410.         register int i, maxy;
  411.         if (amount > 0) 
  412.             for(i = y, maxy = y + numlines - amount; i < maxy; i++) {
  413.                 templ  = disp.plines[i];
  414.         templs = disp.pstyles[i];
  415.                 disp.plines[i] = disp.plines[i + amount];
  416.         disp.pstyles[i] = disp.pstyles[i + amount];
  417.         disp.plines[i + amount] = templ;
  418.         disp.pstyles[i + amount] = templs;
  419.     }
  420.     else if (amount < 0)
  421.         for (i = y + numlines - 1,maxy = y - amount; i >= maxy; i--) {
  422.         templ = disp.plines[i];
  423.         templs = disp.pstyles[i];
  424.         disp.plines[i] = disp.plines[i + amount];
  425.         disp.pstyles[i] = disp.pstyles[i + amount];
  426.             disp.plines[i + amount] = templ;
  427.         disp.pstyles[i + amount] = templs;
  428.     }
  429.     }
  430.  
  431.     if (amount > 0) {
  432.     MAXBOUNDCK(amount, numlines);
  433.     DSEMPTYLINE(y + numlines - amount, y + numlines);
  434.     } else {
  435.     if ((amount = -amount) > numlines)
  436.         amount = numlines;
  437.     DSEMPTYLINE(y, y+amount);
  438.     }
  439. }
  440.  
  441. /*
  442.  * put a string at x, y
  443.  */
  444. static void wmputs(int x, int y, unsigned char *stng, int style)
  445. {
  446.     int len, pos; 
  447.     char temp[MAXWIDTH];
  448.     int wflag = (STYLEFLAG(y) & DOUBLE_MASK) != 0;
  449.  
  450.     if (disp.insert) {
  451.     register int linelen = LINELEN(y);
  452.     for (pos = 0; pos < MAXWIDTH-1 && (temp[pos] = stng[pos]); pos++);
  453.     for (len = x; pos < MAXWIDTH-1 && len < linelen; len++)
  454.         temp[pos++] = TEXTPOS(len, y);
  455.     temp[MAXBOUND(pos, (disp.winwidth >> wflag) - 1)] = '\0';
  456.     stng = temp;
  457.     } 
  458.     {
  459.         register int tx = SLIMIT((x),disp.winwidth);
  460.         register int ty = SLIMIT((y),disp.winheight);
  461.         register char *temp = (stng);
  462.         if (temp != NULL && *temp) {
  463.         for ((len) = LINELEN(ty); (len) < tx; (len)++) {
  464.             TEXTPOS((len), ty) = ' ';
  465.             STYLEPOS((len), ty) = 0;
  466.         }
  467.         /* stuff the characters into the buffer */
  468.         for ((len)=0;*temp;) {
  469.             (len)++;
  470.             TEXTPOS(tx,ty) = *temp++;
  471.             STYLEPOS(tx++,ty) = (style);
  472.         if (tx >= disp.winwidth) {
  473.             LINELENST(ty) = disp.winwidth;
  474.             tx=disp.winwidth-1;
  475.             break;
  476.             }
  477.         }
  478.         if (LINELEN(ty) < tx)
  479.             LINELENST(ty) = tx;
  480.         STYLEFLAG(y) |= (style);
  481.         }
  482.     }
  483.  
  484.     if (!rp)
  485.     return;
  486.  
  487. #if 0    
  488.     BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(x << wflag), POSY(y), 
  489.                       wm.font.w * len << wflag, wm.font.h, 
  490.               disp.invert ? BLACK : WHITE);
  491. #endif
  492.  
  493.     styleput(x, y, stng, len, style);
  494. }
  495.  
  496.     
  497. /*
  498.  * quick clear of the entire display
  499.  */
  500. void dsclearscreen(void)
  501. {
  502.     clear_display();
  503.     cursormode = 0;
  504.     if (rp) INVERTALL(disp.invert ? BLACK : WHITE);
  505.     clearSelection();
  506.     dssetfont(disp.style, disp.cury);
  507. }
  508.  
  509. /*
  510.  * clear region routines
  511.  */
  512. void dsclear(int x, int y, int x1, int y1)
  513. {
  514.     if (x > x1)
  515.     SWAP(x,x1);
  516.     if (y > y1)
  517.     SWAP(y,y1);
  518.  
  519.     DSCLEAR(x, y, x1, y1);
  520.  
  521.     if (rp) {
  522.     int wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) !=0;
  523.     BltBitMapRastPort(rp->BitMap, 0, 0, rp, 
  524.               POSX(x << wflag), 
  525.               POSY(y),
  526.               (x1 - x + 1) * wm.font.w << wflag, 
  527.               (y1 - y + 1) * wm.font.h,
  528.               (disp.invert ? BLACK : WHITE));
  529.     }
  530. }
  531.  
  532. /*
  533.  * delete n characters on current line into cursor
  534.  */
  535. void dsdelete(int n)
  536. {
  537.     char    deleteme[MAXWIDTH];
  538.     int        pos, i, linelen = LINELEN(disp.cury);
  539.     int wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) != 0;
  540.  
  541.     if (disp.curx + n >= (disp.winwidth >> wflag))
  542.     n = (disp.winwidth >> wflag) - disp.curx - 1;
  543.     if (!n)
  544.     return;
  545.     if ((pos = disp.curx + n) > linelen) {
  546.     if (linelen > disp.curx)
  547.         dsclear(disp.curx, disp.cury, linelen, disp.cury);
  548.     } else if (linelen) {
  549.     for (i = 0; pos < linelen; pos++)
  550.         deleteme[i++] = TEXTPOS(pos, disp.cury);
  551.     deleteme[i] = '\0';
  552.     dsclear(linelen - 1 - n, disp.cury, linelen - 1, disp.cury);
  553.     LINELENST(disp.cury) = linelen-n;
  554.     wmputs(disp.curx, disp.cury, deleteme, disp.style);
  555.     }
  556. }
  557.  
  558. /*
  559.  * put a string to the display
  560.  */
  561. void dsputs(char *s)
  562. {
  563.     int len = strlen(s), dlen;
  564.     char *temp, tempc;
  565.     int wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) != 0;
  566.     
  567.     for (temp = s; len; len -= dlen) {
  568.     if (vt100_yucky_wrap_mode) {
  569.         disp.curx = 0;
  570.         NEWLINE();
  571.         dssetfont(disp.style, disp.cury);
  572.         vt100_yucky_wrap_mode = 0;
  573.         wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) != 0;
  574.     }
  575.     if (len > (disp.winwidth >> wflag) - disp.curx) {
  576.         dlen = (disp.winwidth >> wflag) - disp.curx;
  577.         tempc = temp[dlen];
  578.         temp[dlen]=0;
  579.         wmputs(disp.curx, disp.cury, temp, disp.style);
  580.         temp[dlen] = tempc;
  581.         if (!disp.wrap)
  582.         dlen = len-1;
  583.         temp += dlen;
  584.     } else {
  585.         dlen = len;
  586.         wmputs(disp.curx, disp.cury, temp, disp.style);
  587.         if (np.emulation == EMU_VT102 && 
  588.         disp.curx + dlen == (disp.winwidth >> wflag))
  589.         disp.curx--, vt100_yucky_wrap_mode = 1;
  590.     }
  591.     if ((disp.curx += dlen) >= (disp.winwidth >> wflag)) {
  592.         if (disp.wrap) {
  593.         NEWLINE();
  594.         disp.curx = 0;
  595.         } else
  596.         disp.curx = (disp.winwidth >> wflag) - 1;
  597.     }
  598.  
  599.     dssetfont(disp.style, disp.cury);
  600.     if (np.slow) {
  601.         udelay(100);
  602.     }
  603.     }
  604. }
  605.  
  606. /*
  607.  * invert screen or visual bell
  608.  */
  609. void dsinvert(int invtype)
  610. {
  611.     if (!rp)
  612.     return;
  613.  
  614.     switch (invtype) {
  615.     case INVERT_ON:
  616.         if (!disp.invert) {
  617.         disp.invert = 1;
  618.         INVERTALL(INVERT);
  619.         udelay(8000);
  620.         }
  621.         break;
  622.  
  623.     case INVERT_OFF:
  624.         if (disp.invert) {
  625.         disp.invert = 0;
  626.         INVERTALL(INVERT);
  627.         }
  628.         break;
  629.         
  630.     case VISUAL_BELL:
  631.             INVERTALL(INVERT);
  632.         udelay(10000);
  633.             INVERTALL(INVERT);
  634.         break;
  635.     }
  636. }
  637.  
  638. /*
  639.  * fill the screen with E's
  640.  */
  641. void dstestscreen(void)
  642. {
  643.     DSTEST('E', disp.style);
  644.     (void) redraw_display(1);
  645.     dscursoroff();
  646. }
  647.  
  648. /*
  649.  * Routines handling the selection
  650.  */
  651. #define    ISSELECTION \
  652. (selection.sx != selection.ex || selection.sy != selection.ey)
  653. #define    OUTSIDESEL(x,y)    \
  654.     ((y)<selection.sy || ((y)==selection.sy && (x) < selection.sx) ? \
  655.      -1 : \
  656.      ((y)>selection.ey || ((y)==selection.ey && (x) >= selection.ex) ? 1 : 0))
  657. #define    INSEL(x,y)    (!OUTSIDESEL(x,y))
  658. #define    SELTOPY        (selection.sy + (selection.sx ? 1 : 0))
  659. #define    SELBOTY        (selection.ey - 1)
  660. #define    POSITIVE(x)    ((x) < 0 ? 0 : (x))
  661. #define    ENDDIST(x,y) \
  662.     (POSITIVE(selection.ey-(y)) * disp.winwidth \
  663.      + disp.winwidth - 1 - (x) + selection.ex)
  664. #define    STDIST(x,y) \
  665.     (POSITIVE((y)-SELTOPY-1) * disp.winwidth  \
  666.      + disp.winwidth - 1 - selection.sx + (x))
  667. #define    NEAREND(x,y)    (ENDDIST(x,y) > STDIST(x,y))
  668. #define    REVSEL \
  669. (selection.sy > selection.ey || \
  670.  (selection.sy == selection.ey && selection.sx > selection.ex))
  671.  
  672. struct {
  673.     int    sx, sy,    ex, ey;        /* selection range */
  674. } selection;
  675.  
  676. /* Returns true if selected
  677.  */
  678. int isSelection(void) {
  679.     return ISSELECTION;
  680. }
  681.  
  682. /* Mouse selection handler
  683.  */
  684. void doselection(int action, int x, int y)
  685. {
  686.     int selection_on = ISSELECTION;
  687.  
  688.     if (!rp)
  689.       return;
  690.  
  691.     if (action == LBDOWN) {
  692.     if (ISSELECTION)
  693.         killSelection();
  694.     selection.sx = selection.ex = x;
  695.     selection.sy = selection.ey = y;
  696.  
  697.     } 
  698.     else if((action == LBUP) || (action == LMOVE)) {
  699.     if (selection.ex != x || selection.ey != y)
  700.         extendSelection(selection.ex,selection.ey,x,y);
  701.     selection.ex=x;
  702.     selection.ey=y;
  703.     if(action == LBUP) {
  704.         register int tmp;
  705.         tmp=selection.sy, selection.sy=selection.ey, selection.ey=tmp;
  706.         tmp=selection.sx, selection.sx=selection.ex, selection.ex=tmp;
  707.     }
  708.     }
  709.     if (ISSELECTION ^ selection_on)
  710.     dscursorblink();    
  711. }
  712.  
  713. /*
  714.  * grab a selection -- caller must free the buffer when finished.
  715.  */
  716. char *grabSelection(void)
  717. {
  718.     char *buffer, *temp;
  719.     int sx = selection.sx, ex = selection.ex, endx, endl;
  720.     int sy = selection.sy, ey = selection.ey;
  721.     int buflen;
  722.  
  723.     if (!ISSELECTION)
  724.     return (NULL);
  725.  
  726.     if (sy > ey || (sy == ey && sx > ex)) {
  727.     register int tmp;
  728.  
  729.     tmp = sy, sy=ey, ey = tmp;
  730.     tmp = sx, sx=ex, ex = tmp;
  731.     }
  732.  
  733.     buflen = (ey - sy + 2) * (disp.winwidth + 1); 
  734.     temp = buffer = AllocVec(buflen, MEMF_CLEAR);
  735.  
  736.     for (;sy <= ey; sy++) {
  737.     endx = LINELEN(sy);
  738.     if (sy == ey) {
  739.         MAXBOUNDCK(endx, ex);
  740.         endl = ex;
  741.     } else
  742.         endl = disp.winwidth;
  743.     for (;sx < endx; sx++)
  744.         *temp++ = TEXTPOS(sx, sy);
  745.     sx = 0;
  746.     if (endl > LINELEN(sy))
  747.         *temp++ = '\n';
  748.     }
  749.     *temp = 0;
  750.  
  751.     assert(temp < buffer + buflen);
  752.  
  753.     return (buffer);
  754. }
  755.  
  756. /* invert/extend the selection range
  757.  */
  758. void extendSelection(int sx, int sy, int ex, int ey)
  759. {
  760.   int topy, boty;
  761.  
  762.   if (sy > ey || (sy == ey && sx > ex)) {
  763.     register int tmp;
  764.  
  765.     tmp = sy, sy=ey, ey = tmp;
  766.     tmp = sx, sx=ex, ex = tmp;
  767.   }
  768.   topy = sy + (sx ? 1 : 0);
  769.   boty = ey - 1;
  770.   if (sx == ex && sy == ey)
  771.     return;
  772.   if (sy == ey) 
  773.     BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(sx), POSY(sy), 
  774.               wm.font.w*(ex-sx), wm.font.h, INVERT);
  775.   else {
  776.     if (sx && sx < disp.winwidth)
  777.       BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(sx), POSY(sy),
  778.             wm.font.w*(disp.winwidth-sx), wm.font.h, INVERT);
  779.     if (boty-topy+1 > 0)
  780.       BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(0), POSY(topy),
  781.             wm.font.w * disp.winwidth, 
  782.             wm.font.h * (boty - topy + 1), INVERT);
  783.     if (ex)
  784.       BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(0), POSY(ey), 
  785.             wm.font.w*ex, wm.font.h, INVERT);
  786.   }
  787. }
  788.  
  789. void invertSelection(void)
  790. {
  791.     extendSelection(selection.sx, selection.sy, selection.ex, selection.ey);
  792. }
  793.  
  794. void killSelection(void)
  795. {
  796.     invertSelection();
  797.     selection.ey=selection.sy;
  798.     selection.ex=selection.sx;
  799. }
  800.  
  801. void clearSelection(void)
  802. {
  803.     selection.ey = selection.sy = selection.ex = selection.sx = 0;
  804. }
  805.  
  806. /*
  807.  * Initialization and cleanup
  808.  */
  809. int initdrawing(struct RastPort *rastport)
  810. {
  811.   if (!rp) {
  812.     myrp = *(rastport);
  813.     rp = &myrp;
  814.  
  815.     SetAPen(rp, 1);
  816.     SetBPen(rp, 0);
  817.     SetWrMsk(rp, 1);
  818.     SetDrMd(rp, DEFDRMD);
  819.     return 1;
  820.   } else {
  821.     return 0;
  822.   }
  823. }
  824.  
  825. void deinitdrawing(void)
  826. {
  827.     rp = NULL;
  828. }
  829.  
  830. #ifdef OWNICONIFY
  831. /* Do Not do ANYTHING after calling unmapwindow!! This is only used for 
  832.  * iconification.  Saves the state information, then closes the window.
  833.  */
  834. void
  835. unmapwindow(void)
  836. {
  837.     struct IntuiMessage *msg;
  838.     
  839.     while (msg = (struct IntuiMessage *)
  840.        GetMsg(w->UserPort)) ReplyMsg((struct Message *)msg);
  841.     DisplayOff = 1;
  842.     ClearMenuStrip(w);
  843.     nw.TopEdge = w->TopEdge;
  844.     nw.LeftEdge = w->LeftEdge;
  845.     nw.Width = w->Width;
  846.     nw.Height = w->Height;
  847.     nw.MaxWidth = w->MaxWidth;
  848.     nw.MaxHeight = w->MaxHeight;
  849.     nw.MinWidth = w->MinWidth;
  850.     nw.MinHeight = w->MinHeight;
  851.     nw.Flags = w->Flags;
  852.     nw.Title = w->Title;
  853.     CloseWindow(w);
  854.     rp = w = NULL;            /* no dangling references */
  855. }
  856.  
  857. /* Undoes a call to unmapwindow() everything should return to the way it was
  858.  * before the call 
  859.  */
  860. void
  861. mapwindow(void) 
  862. {
  863.     if(!(w = OpenWindow(&nw))) 
  864.         fatalError("Can't reopen window!!!!!");
  865.     /* We have a new RastPort!! */
  866.     myrp = *(w->RPort);
  867.     rp = &myrp;
  868.     SetAPen(rp, 1);
  869.     SetBPen(rp, 0);
  870.     SetWrMsk(rp, 1);
  871.     SetDrMd(rp, DEFDRMD);
  872.  
  873.     /* => setmenus() */
  874.     SetMenuStrip(w, &editmenu);
  875.     /* Now, everything should be back the way it was before */
  876.     DisplayOff = 0;
  877.     redraw_display(1);
  878. }
  879. #endif
  880.  
  881. /* Local Variables: */
  882. /* c-style:C++ */
  883. /* End: */
  884.